/***
 * 权限模型设计如下:
 * 每一个权限是一个简单的键值对，可以分为多种不同的类型，包括模块、菜单、字段等等，方便进行展示和管理；
 * 不同的权限可以组合成为一个权限组；
 * 每一个角色可以分配多个不同的权限组（！！为角色分配权限组的时候，可以限定单位，满足更复杂的权限限定需求）；
 * 角色可以分配给不同的用户或单位。
 * 权限层次从低到高是权限项，权限组，角色，用户/单位。
 * 不同应用系统的权限分别管理，通过APPId来区分。
 */

using System.Collections.Generic;
using System.Linq;
using WebAuth.Constans;
using WebAuth.DAO;
using WebAuth.Models;

namespace WebAuth.Bussiness
{
    public class AuthManager
    {
        UserAuthsMap _userAuthsMap = new UserAuthsMap();
        private static AuthManager _me;

        public static AuthManager GetAuthManager()
        {
            if (_me == null)
            {
                _me = new AuthManager();
            }

            return _me;
        }

        /***
         * After modifying the characters,authentication group etc.
         * the easiest way to make sure the user-auth maps being right is to reload the whole cache.
         * In order to reduce the payload,maybe I can try to deal with different ways of change separately.
         * Way1: use version control
         *    The authentication version increases after modifying the characters,authentication group bindings,
         *every time a user request comes,we will check the cache version of this user's AuthItemsCache,if it's not equal to the
         *authentication version,we will refresh the AuthItemsCache and set it's version equal to the version just before
         *the refreshing. 
         */

        /***
         * ownerId can by userid,departmentid etc.,
         * appId is used to distinguish every application system
         */

        private int RefreshAuthMapCache(string appId)
        {
            int count = 0;

            return count;
        }

        /***
         * Modify the authentication bindings. 
         */
        public bool ModifyAuth(string ownerId, string[] idArray, OwnerType authCategory)
        {
            List<string> originalIdList = GetOriginalIdList(ownerId, authCategory);
            List<string> removeIdList = GetToDelIdList(originalIdList, idArray);
            List<string> addIdList = GetToAddIdList(originalIdList, idArray);
            bool addOk = false, removeOk = false;
            removeOk = removeIdList.Count <= 0 || RemoveAuth(ownerId, removeIdList, authCategory);
            addOk = addIdList.Count <= 0 || AddAuth(ownerId, addIdList, authCategory);
            return removeOk & addOk;
        }

        private List<string> GetToAddIdList(List<string> originalIdList, string[] idArray)
        {
            List<string> resList = new List<string>();
            foreach (var id in idArray)
            {
                if (!originalIdList.Contains(id))
                {
                    resList.Add(id);
                }
            }

            return resList;
        }

        private List<string> GetToDelIdList(List<string> originalIdList, string[] idArray)
        {
            List<string> resList = new List<string>();
            foreach (var oid in originalIdList)
            {
                if (!idArray.Contains(oid))
                {
                    resList.Add(oid);
                }
            }

            return resList;
        }

        private List<string> GetOriginalIdList(string ownerId, OwnerType authCategory)
        {
            throw new System.NotImplementedException();
        }


        public bool AddAuth(string ownerId, List<string> idArray, OwnerType ownerType)
        {
            switch (ownerType)
            {
                case OwnerType.Character:
                {
                    break;
                }
                case OwnerType.AuthGroup:
                {
                    break;
                }
            }

            return true;
        }
        /***
         * Todo:consider to check if the case is to remove all the auths items,use diffrent way could speed up the process.
         */

        public bool RemoveAuth(string ownerId, List<string> idArray, OwnerType ownerType)
        {
            switch (ownerType)
            {
                case OwnerType.Character:
                {
                    break;
                }
                case OwnerType.AuthGroup:
                {
                    break;
                }
            }

            return true;
        }

        /***
         * check the user authentication
         */
        public bool CheckAuth(string userid, string authItemId)
        {
            if (!_userAuthsMap.ContainsKey(userid))
            {
                if (!LoadUserAuthMap(userid))
                {
                    return false;
                }
            }

            var cacheManager = CacheManager.GetCacheManager();
            while (_userAuthsMap[userid].GetCacheVersion() != cacheManager.GetCachVersion())
            {
                LoadUserAuthMap(userid);
            }

            if (_userAuthsMap[userid].ContainsKey(authItemId))
            {
                return true;
            }

            return false;
        }

        private bool LoadUserAuthMap(string userid)
        {
            var cacheManager = CacheManager.GetCacheManager();
            cacheManager.GetModelSet(out Dictionary<string, User> userSet);
            if (!userSet.ContainsKey(userid))
            {
                return false;
            }

            _userAuthsMap[userid] = new AuthItemsMap(userid);
            _userAuthsMap[userid].LoadAuthItems(userid);
            return true;
        }
    }
}